import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.HashSet;



public class Hand implements Comparable<Hand>{
	ArrayList<Card> cards;
	ArrayList<ArrayList<Card>> bestUklady;
	
	Hand() {
		cards = new ArrayList<Card>(4);
		bestUklady = new ArrayList<ArrayList<Card>>();
	}
	
	public String toString() {
		String stringHand = new String("");
		for (Card card : cards) {
			stringHand += card.toString() + " ";
		}
		return stringHand;
	}
	
	public int compareTo(Hand hand) {
		
		this.bestUklady = this.getBestUklady(this.getMaxUklady(this.getUklady(Hand.powerset(this.cards))));
		hand.bestUklady = hand.getBestUklady(hand.getMaxUklady(hand.getUklady(Hand.powerset(hand.cards))));
		ArrayList<ArrayList<Card>> playersUklady = new ArrayList<ArrayList<Card>>(2);
		playersUklady.add(this.bestUklady.get(0));
		playersUklady.add(hand.bestUklady.get(0));
		
		ArrayList<ArrayList<Card>> best = getBestUklady(getMaxUklady(playersUklady));
		if (best.size() == 2) {
			return 0;
		} else {
			if (best.get(0) == this.bestUklady.get(0)) {
				return 1;
			} else {
				return -1;
			}
		}
	}
	
	public ArrayList<ArrayList<Card>> getBestUklady(ArrayList<ArrayList<Card>> maxUklady) {
		int size = maxUklady.size();
		boolean[] isBest = new boolean[size];
		Arrays.fill(isBest, true);
		ArrayList<ArrayList<Card>> bestUklady = new ArrayList<ArrayList<Card>>();
		
		for (ArrayList<Card> maxUklad : maxUklady) {
			Collections.sort(maxUklad);
		}
		
		for (int i = 0; i < maxUklady.get(0).size(); i++) {
			ArrayList<Card> cardsToCompare = new ArrayList<Card>();
			for (int j = 0; j < maxUklady.size(); j++) {
				if (isBest[j]) {
					cardsToCompare.add(maxUklady.get(j).get(i));
				}
			}
			Card bestCard = Collections.max(cardsToCompare);
			for (int j = 0; j < cardsToCompare.size(); j++) {
				if (bestCard.compareTo(cardsToCompare.get(j)) > 0) {
					isBest[j] = false;
				}
			}
		}
		
		for (int j = 0; j < maxUklady.size(); j++) {
			if (isBest[j]) {
				bestUklady.add(maxUklady.get(j));
			}
		}
		
		return bestUklady;
		
	}
	
	public ArrayList<ArrayList<Card>> getMaxUklady(ArrayList<ArrayList<Card>> uklady) {
		ArrayList<ArrayList<Card>> ukladyToRemove = new ArrayList<ArrayList<Card>>();

		int maxSize = 0;
		for (ArrayList<Card> uklad : uklady) {
			if (uklad.size() > maxSize) {
				maxSize = uklad.size();
			}
		}
		for (int i = 0; i < uklady.size(); i++) {
			if (uklady.get(i).size() < maxSize) {
				ukladyToRemove.add(uklady.get(i));
			}
		}
		for (ArrayList<Card> uklad : ukladyToRemove) {
			uklady.remove(uklad);
		}
		return uklady;
	}
	
	public ArrayList<ArrayList<Card>> getUklady(ArrayList<ArrayList<Card>> powerset) {
		ArrayList<ArrayList<Card>> subsetsToRemove = new ArrayList<ArrayList<Card>>();
		for (int i = 0; i < powerset.size(); i++) {
			if (hasDuplicates(powerset.get(i))) {
				subsetsToRemove.add(powerset.get(i));
			}
		}
		for (ArrayList<Card> subset : subsetsToRemove) {
			powerset.remove(subset);
		}
		return powerset;
	}
	
	boolean hasDuplicates(ArrayList<Card> subset) {
		ArrayList<String> ranks = new ArrayList<String>();
		ArrayList<String> suites = new ArrayList<String>();
		boolean hasRankDuplicates = false, hasSuitDuplicates = false;
		
		for (Card card : subset) {
			ranks.add(card.getRank());
		}
		Set<String> ranksSet = new HashSet<String>(ranks);
		if(ranksSet.size() < ranks.size()){
			hasRankDuplicates = true;
		}
		
		for (Card card : subset) {
			suites.add(card.getSuit());
		}
		Set<String> suitesSet = new HashSet<String>(suites);
		if(suitesSet.size() < suites.size()){
			hasSuitDuplicates = true;
		}
		
		return hasRankDuplicates || hasSuitDuplicates;
	}
	
	public static <T> ArrayList<ArrayList<T>> powerset(Collection<T> list) {
		ArrayList<ArrayList<T>> ps = new ArrayList<ArrayList<T>>();
		  ps.add(new ArrayList<T>());   // add the empty set
		 
		  // for every item in the original list
		  for (T item : list) {
			  ArrayList<ArrayList<T>> newPs = new ArrayList<ArrayList<T>>();
		 
		    for (ArrayList<T> subset : ps) {
		      // copy all of the current powerset's subsets
		      newPs.add(subset);
		 
		      // plus the subsets appended with the current item
		      ArrayList<T> newSubset = new ArrayList<T>(subset);
		      newSubset.add(item);
		      newPs.add(newSubset);
		    }
		 
		    // powerset is now powerset of list.subList(0, list.indexOf(item)+1)
		    ps = newPs;
		  }
		  return ps;
		}

}
